package com.hqyj.finance.server.bill.financebill.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.cell.CellSetter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hqyj.finance.server.bill.financebill.entity.UserExpenses;
import com.hqyj.finance.server.bill.financebill.entity.UserIncome;
import com.hqyj.finance.server.bill.financebill.mapper.UserIncomeMapper;
import com.hqyj.finance.server.bill.financebill.service.QiniuService;
import com.hqyj.finance.server.bill.financebill.service.UserIncomeService;
import com.hqyj.finance.server.bill.financebill.views.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
public class UserIncomeServiceImpl extends ServiceImpl<UserIncomeMapper, UserIncome> implements UserIncomeService {

    @Value("${myproject.perPageSize}")
    private Integer perPageSize ;

    @Value("${myproject.exportPath}")
    private String exportTempPath;

    @Resource
    private QiniuService qiniuService;

    @Resource
    private UserIncomeMapper userIncomeMapper;
    @Transactional(rollbackOn = Exception.class)
    @Override
    public boolean saveUserIncomeInfo(UserIncome userIncome) throws Exception {
        try {
            return super.save(userIncome);
        }catch (Exception ex){
            ex.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    @Override
    public List<UserIncome> queryUserIncomeInfoByUid(Integer uid) throws Exception {
        QueryWrapper<UserIncome> queryWrapper = new QueryWrapper<UserIncome>();
        queryWrapper.eq("incomeUserId",uid);
        return super.list(queryWrapper);
    }

    @Override
    public Page<UserIncome> queryUserIncomePagerByUid(Integer uid, Integer currentPageNum) throws Exception {
        Page<UserIncome> userIncomePage = new Page<UserIncome>(currentPageNum,perPageSize);
        QueryWrapper<UserIncome> incomeQueryWrapper = new QueryWrapper<UserIncome>();
        incomeQueryWrapper.eq("incomeUserId",uid);
        return userIncomeMapper.selectPage(userIncomePage,incomeQueryWrapper);
    }

    @Override
    public UserIncome queryUserIncomeInfoByIncomesId(Integer id) {
        return super.getById(id);
    }

    @Override
    public UserIncomeMonthsView queryUserIncomeMonthsViewByUid(Integer uid, String realName, String month,Integer currentPageNum) {


        UserIncomeMonthsView userIncomeMonthsView = new UserIncomeMonthsView();
        userIncomeMonthsView.setUid(uid);
        userIncomeMonthsView.setMonths(month);
        userIncomeMonthsView.setRealName(realName);

        Page<UserIncome> page = new Page<UserIncome>(currentPageNum, perPageSize);
        QueryWrapper<UserIncome> queryWrapper = new QueryWrapper<UserIncome>();
        queryWrapper.eq("incomeUserId", uid);
        queryWrapper.like("incomeTime", month);
        queryWrapper.orderByAsc("incomeTime");

        Page<UserIncome> pager = userIncomeMapper.selectPage(page, queryWrapper);
        List<UserIncome> userIncomeList = super.list(queryWrapper);

        if (userIncomeList != null && userIncomeList.size() > 0) {
            double totalFee = 0;
            for (UserIncome income : userIncomeList) {
                totalFee += Double.parseDouble(income.getIncomeNum());
            }
            userIncomeMonthsView.setTotalFee(totalFee);
        }

        userIncomeMonthsView.setUserIncomesList(userIncomeList);
        userIncomeMonthsView.setUserIncomePage(pager);
        return userIncomeMonthsView;
    }

    private List<List<String>> UserIncomeListConvertToExcelRows(List<UserIncome> userIncomeList, List<List<String>> rows) {
        for (UserIncome income : userIncomeList) {
            List<String> row1 = CollUtil.newArrayList(income.getIncomeId().toString(), income.getIncomeTime(), income.getIncomeUserId().toString(), income.getIncomeUser(), income.getIncomeNum(), income.getIncomeSort(), income.getIncomeRemark(), income.getVoucherUrl());
            rows.add(row1);
        }
        return rows;
    }

    @Override
    public String exportUserIncomeMonthViewAsExcel(UserIncomeMonthsView userIncomeMonthsView) throws Exception {
        try {
            String destFile = this.exportTempPath + File.separator + IdUtil.fastSimpleUUID()+".xlsx";
            // 通过工具类创建writer
            ExcelWriter writer = ExcelUtil.getWriter(destFile);
            String realName = userIncomeMonthsView.getRealName();
            String month = userIncomeMonthsView.getMonths();
            String totalFee = userIncomeMonthsView.getTotalFee().toString();
            //自定义标题别名
            writer.addHeaderAlias("incomeId", "流水号");
            writer.addHeaderAlias("incomeTime", "收入日期");
            writer.addHeaderAlias("incomeUserId", "用户编号");
            writer.addHeaderAlias("incomeUser", "姓名");
            writer.addHeaderAlias("incomeNum", "收入金额");
            writer.addHeaderAlias("incomeSort", "收入分类");
            writer.addHeaderAlias("incomeRemark", "收入备注");
            writer.addHeaderAlias("voucherUrl", "凭证");

            // 合并单元格后的标题行，使用默认标题样式
            writer.merge(7, realName + "" + month + "月收入明细表");

            List<List<String>> rows = new ArrayList<List<String>>();

            List<String> header = CollUtil.newArrayList("流水号", "收入日期", "用户编号", "姓名", "收入金额", "收入分类", "收入备注", "凭证");
            rows.add(header);

            UserIncomeListConvertToExcelRows(userIncomeMonthsView.getUserIncomesList(), rows);

            writer.getSheet().setColumnWidth(1, 5000);
            writer.getSheet().setColumnWidth(5, 5000);
            writer.getSheet().setColumnWidth(6, 5000);
            writer.getSheet().setColumnWidth(7, 20000);
            // 一次性写出内容，使用默认样式，强制输出标题
            writer.write(rows, true);

            //单独再写一行，总金额
            List<Object> row = ListUtil.of((CellSetter) cell -> cell.setCellValue("收入总金额：" + totalFee));
            writer.writeRow(row);
            // 关闭writer，释放内存
            writer.close();

            return qiniuService.saveExcelFile(new File(destFile));
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public UserIncomeMonthsCharts queryUserIncomeMonthsChartsByUid(Integer uid, String realName, String month) {
        UserIncomeMonthsCharts userIncomeMonthsCharts = new UserIncomeMonthsCharts();
        UserIncomeMonthsView userIncomeMonthsView = queryUserIncomeMonthsViewByUid(uid, realName, month, 1);
        List<UserIncome> userIncomeList = userIncomeMonthsView.getUserIncomesList();
        for (UserIncome userIncome : userIncomeList) {
            userIncomeMonthsCharts.getIncomeDateList().add(userIncome.getIncomeTime());
            userIncomeMonthsCharts.getIncomeMoneyList().add(Double.parseDouble(userIncome.getIncomeNum()));
        }
        return userIncomeMonthsCharts;
    }

    @Override
    public UserIncomeCatalogMonthsCharts queryUserIncomeCatalogMonthsCharts(Integer uid, String realName, String month) {
        UserIncomeCatalogMonthsCharts userIncomeCatalogMonthsCharts = new UserIncomeCatalogMonthsCharts();
        UserIncomeMonthsView userIncomeMonthsView = queryUserIncomeMonthsViewByUid(uid, realName, month, 1);

        List<UserIncome> userIncomesList = userIncomeMonthsView.getUserIncomesList();
        Map<String, Double> map = userIncomeCatalogMonthsCharts.getIncomeCatalogMaps();
        for (UserIncome userIncome : userIncomesList) {
            String key = userIncome.getIncomeSort();
            if (map.containsKey(key)) {
                map.put(key, map.get(key) + Double.parseDouble(userIncome.getIncomeNum()));
            } else {
                map.put(key, Double.parseDouble(userIncome.getIncomeNum()));
            }
        }
        return userIncomeCatalogMonthsCharts;
    }
}
